package tcp

import (
	"context"
	"fmt"
	"go_redis_service/interface/ITcp"
	"go_redis_service/lib/logger"
	"net"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

type Config struct {
	Address string
}

// ListenAndServeWithSignal
// @Description: 启动tcp服务
// @param cfg
// @param handler
// @return error
func ListenAndServeWithSignal(cfg *Config, handler ITcp.Handler) error {
	// 信号注册
	closeChan := make(chan struct{})
	sigChan := make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	// 监听到信号后 通知下方关闭
	go func() {
		sig := <-sigChan
		switch sig {
		case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			closeChan <- struct{}{}
		}
	}()
	// 启动服务
	listener, err := net.Listen("tcp", cfg.Address)
	if err != nil {
		return err
	}
	logger.Info(fmt.Sprintf("bind:%s start listening...", cfg.Address))
	ListenAndServe(listener, handler, closeChan)
	return nil
}

// ListenAndServe
// @Description: 处理Conn
// @param listener
// @param handler
// @param closeChan
func ListenAndServe(listener net.Listener, handler ITcp.Handler, closeChan <-chan struct{}) {
	// 监听到信号执行关闭操作 -- 异常关闭
	go func() {
		<-closeChan
		logger.Info("exception shutting down...")
		_ = listener.Close()
		_ = handler.Close()
	}()
	// 处理完成后执行关闭操作 -- 正常关闭
	defer func() {
		_ = listener.Close()
		_ = handler.Close()
	}()

	ctx := context.Background()
	// 负责记录连接数
	var waitDone sync.WaitGroup
	for true {
		conn, err := listener.Accept()
		if err != nil {
			break
		}
		logger.Info("accept link")
		waitDone.Add(1)
		go func() {
			defer func() {
				waitDone.Done()
			}()
			handler.Handle(ctx, conn)
		}()
	}
	// 等所有连接服务完毕
	waitDone.Wait()
}
